package model;

import java.util.LinkedList;
import java.util.Observable;
import java.util.Timer;
import java.util.TimerTask;

import model.mobs.Mob;

/**
 * Modello principale del gioco, che contiene tutte le informazioni sulla partita in corso.
 * @author Max
 *
 */
public class MainModel extends Observable {

	public static final long UPDATE_TIME_MS = 10;
	private static MainModel mainModel;
	private LinkedList<Mob> mobs = new LinkedList<Mob>();
	private Ship userShip;
	private long score;
	private long initTime;
	private Timer mainTimer = new Timer();
	private ScoreCalculator scoreCalculator;
	
	/**
	 * Restituisce l'istanza del modello.
	 * @return istanza del modello
	 */
	public static MainModel getInstance() {
		if(mainModel == null) {
			mainModel = new MainModel();
		}
		return mainModel;
	}
	
	private MainModel() {	//costruttore private (SINGLETON!)
	}
	
	/**
	 * Imposta l'algotirmo di calcolo del punteggio.
	 * @param scoreCalculator
	 */
	public void setScoreCalculator(ScoreCalculator scoreCalculator) {
		this.scoreCalculator = scoreCalculator;
	}
	
	/**
	 * Aggiunge un mob alla lista dei mob attivi.
	 * @param mob
	 */
	public void addMob(Mob mob) {
		mobs.add(mob);
	}
	
	public void setUserShip(Ship userShip ){
		this.userShip = userShip;
	}
	
	/**
	 * Restituisce la Ship dell'utente principale.
	 * @return ship dell'utente
	 */
	public Ship getUserShip(){
		return userShip;
	}
	
	/**
	 * Restituisce il numero di mob attivi.
	 * @return numero di mob attivi
	 */
	public int getMobCount() {
		return mobs.size();
	}
	
	/**
	 * Inizia una nuova partita.
	 */
	public void startGame() {
		score = 0;
		mobs.clear();
		initTime = System.currentTimeMillis();
		mainTimer.scheduleAtFixedRate(new TimerTask() {
			@Override
			public void run() {
				updateScore(scoreCalculator.getNewScore(System.currentTimeMillis() - initTime));
				//TODO: altre robe..
			}
		}, 0, UPDATE_TIME_MS);
	}
	
	/**
	 * Termina la partita in corso.
	 */
	public void endGame() {
		mainTimer.cancel();
		//TODO: altre robe ancora da definire
	}
	
	/**
	 * Aggiorna il punteggio.
	 * @param score
	 */
	public void updateScore(long score) {
		this.score = score;
	}
	
	/**
	 * Restituisce il punteggio corrente.
	 * @return punteggio
	 */
	public long getScore() {
		return score;
	}
	
}
